
<!DOCTYPE html>
<html>
<head>
    <title>Qunee with LeafLetjs</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <style>
        #panel{
            overflow: hidden;
        }
        #canvas{
            width: 100%;
            height: 100%;
        }
        body{
            margin: 0px;
        }
        .Q-Tooltip{
            font-size: 9pt;
        }
    </style>
    <!--<script src="lib/jquery-1.10.1.min.js"></script>-->
    <link rel="stylesheet" href="/static/lib/qunee2.6.2/leaflet.css" />
    <script src="/static/lib/qunee2.6.2/leaflet.js"></script>
    <script src="/static/lib/qunee2.6.2/leaflet.ChineseTmsProviders.js"></script>
    <script src="/static/lib/qunee2.6.2/qunee-min.js?v=1.5.1b" ></script>
    <script src="/static/lib/qunee2.6.2/LeafletGraph.js"></script>
</head>
<body>
<div id="panel" style="position: absolute; top: 0px; bottom: 0px; width: 100%">
    <div id="canvas"></div>
</div>
</body>
<script>
    function FlowingSupport(graph) {
        this.flowMap = {};
        this.graph = graph;
    }
    FlowingSupport.prototype = {
        flowMap: null,
        length: 0,
        gap: 40,
        graph: null,
        addFlowing: function (edgeOrLine, count, byPercent) {
            var flowList = this.flowMap[edgeOrLine.id];
            if(!flowList){
                flowList = this.flowMap[edgeOrLine.id] = [];
                this.length++;
            }
            count = count || 1;
            while(--count >= 0){
                var ui = new Q.ImageUI("flow.png");
                ui.layoutByPath = true;
                ui.position = {x: 0, y: 0};
                ui.size = {width: 20};
                ui.renderColor = "#F00";
                flowList.push(ui);
                flowList.byPercent = byPercent;
                edgeOrLine.addUI(ui);
            }
        },
        removeFlowing: function(id){
            var flowList = this.flowMap[id];
            if(!flowList){
                return;
            }
            var edgeOrLine = this.graph.getElement(id);
            if(edgeOrLine){
                flowList.forEach(function(ui){
                    edgeOrLine.removeUI(ui);
                })
            }
            this._doRemove(id);
        },
        _doRemove: function(id){
            delete this.flowMap[id];
            this.length--;
        },
        timer: null,
        perStep: 10,
        stop: function(){
            clearTimeout(this.timer);
        },
        start: function(){
            if(this.timer){
                clearTimeout(this.timer);
            }
            var offset = 0;
            var scope = this;
            scope.timer = setTimeout(function A() {
                if (!scope.length) {
                    scope.timer = setTimeout(A, 2000);
                    offset = 0;
                    return;
                }
                offset += 1;
                for(var id in scope.flowMap){
                    var ui = scope.graph.getUI(id);
                    if(!ui){
                        scope._doRemove(id);
                        continue;
                    }
                    var lineLength = ui.length;
                    if(!lineLength){
                        continue;
                    }
                    var flowList = scope.flowMap[id];
                    if(flowList.byPercent){
                        //按百分比，0 - 1跑完整条线，线长度不同，速度也不同，跑完一圈的时间相同
                        var x = offset * 2;
                        var gap = 15;
                        scope.flowMap[id].forEach(function(ui){
                            ui.position = {x: (x % 100) / 100, y: 0};
                            x += gap;
                        });
                    }else{
                        //按固定距离移动，速度相同，线条越长跑完一圈的时间越长
                        var x = offset * scope.perStep;
                        scope.flowMap[id].forEach(function(ui){
                            ui.position = {x: x % lineLength, y: 0};
                            x += scope.gap;
                        });
                    }
                    scope.graph.invalidateUI(ui);

                    //dashed line
                    var data = ui.data;
                    if(data instanceof Q.Edge){
                        if(data.getStyle(Q.Styles.EDGE_LINE_DASH)){
                            data.setStyle(Q.Styles.EDGE_LINE_DASH_OFFSET, -offset);
                        }
                    }else if(data instanceof Q.ShapeNode){
                        if(data.getStyle(Q.Styles.SHAPE_LINE_DASH)) {
                            data.setStyle(Q.Styles.SHAPE_LINE_DASH_OFFSET, -offset);
                        }
                    }
                }
                scope.timer = setTimeout(A, 200);
            }, 200);
        }
    }

    var map, graph;
    function initMap(mapId, lat, lng, zoom) {
        var map = L.map(mapId).setView([lat, lng], zoom);
        var normalm = L.tileLayer.chinaProvider('GaoDe.Normal.Map', {maxZoom: 18, minZoom: 3});
        map.addLayer(normalm);
        var osm = new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png');
        //mapabc china map
        L.control.layers({OSM: osm, 高德: normalm}).addTo(map);
        return map;
    }
    function init() {
        map = initMap("canvas", 31.25, 121.45, 7);

        graph = new MapGraph(map);
        var flowingSupport = new FlowingSupport(graph);
        graph.callLater(function(){
            flowingSupport.start();
        })

        function createEdge(name, a, b) {
            var edge = graph.createEdge(name, a, b);
            edge.setStyle(Q.Styles.ARROW_TO, false);
            flowingSupport.addFlowing(edge, 3);
            return edge;
        }

        function createNode(name, lon, lat) {
            var node = graph.createNodeByLonLat(name, lon, lat);
            node.image = Q.Graphs.server;
            node.size = {width: 20};
            //node.setStyle(Q.Styles.SHAPE_FILL_COLOR, "#58F");
            //node.setStyle(Q.Styles.SHAPE_FILL_GRADIENT, new Q.Gradient(Q.Consts.GRADIENT_TYPE_LINEAR, [Q.toColor(0x44EEEEEE), Q.toColor(0x44000000)], null, Math.PI / 2));
            node.setStyle(Q.Styles.LABEL_OFFSET_Y, 10);
            node.setStyle(Q.Styles.LABEL_PADDING, 3);
            node.setStyle(Q.Styles.LABEL_BORDER, 0.5);
            node.setStyle(Q.Styles.LABEL_BACKGROUND_COLOR, Q.toColor(0xCCEEEEEE));
            return node;
        }

        graph.callLater(function () {
            Q.loadJSON("./china_city.json", function (json) {
                var nodes = [];
                for (var name in json) {
                    var v = json[name];
                    var first = null;
                    for (var n in v) {
                        var info = v[n];
                        var node = createNode(n, info.x, info.y);
                        node.size = {width: 20};
                        node.tooltip = n + "\n" + info.x + ", " + info.y;

                        info.x = parseFloat(info.x);
                        info.y = parseFloat(info.y);

//                        var node2 = createNode(null, info.x + Math.random(), info.y + Math.random());
//                        node2.size = {width: 8};
//                        node2.zoom = 6;
//                        var node3 = createNode(null, info.x + Math.random(), info.y + Math.random());
//                        node3.size = {width: 6};
//                        node3.zoom = 10;
//                        var node4 = createNode(null, info.x + Math.random(), info.y + Math.random());
//                        node4.size = {width: 4};
//                        node4.zoom = 12;

                        if (!first) {
                            first = node;
                            nodes.push(node);
                        } else {
                            node.zoom = 8;
                            node.size = {width: 10};
                            node.name = null;
                            if (Q.randomBool()) {
                                createEdge(node, first).setStyle(Q.Styles.EDGE_COLOR, "#888");
                            }
                        }
                    }
                }

                var i = 0;
                while (i++ < nodes.length) {
                    var a = nodes[Q.randomInt(nodes.length)];
                    var b = nodes[Q.randomInt(nodes.length)];
                    if (b != a) {
                        createEdge(a, b);
                        if(Q.randomInt(3) > 1){
                            createEdge(a, b);
                        }
                    }
                }

                //alert(graph.graphModel.length)
            });
        })
    }
    init();
</script>
</html>